#pragma once

// Math and base include
#include <Common/Base/hkBase.h>
#include <Common/Base/System/hkBaseSystem.h>
#include <Common/Base/System/Error/hkDefaultError.h>
#include <Common/Base/Memory/System/Util/hkMemoryInitUtil.h>
#include <Common/Base/Monitor/hkMonitorStream.h>
#include <Common/Base/Memory/System/hkMemorySystem.h>

// Dynamics includes
#include <Physics/Collide/hkpCollide.h>										
#include <Physics/Collide/Agent/ConvexAgent/SphereBox/hkpSphereBoxAgent.h>	
#include <Physics/Collide/Shape/Convex/Box/hkpBoxShape.h>					
#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h>				
#include <Physics/Collide/Dispatch/hkpAgentRegisterUtil.h>					

#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastInput.h>			
#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastOutput.h>		

#include <Physics/Collide/Filter/Group/hkpGroupFilter.h>
#include <Physics/Collide/Filter/Group/hkpGroupFilterSetup.h>

#include <Physics/Dynamics/World/hkpWorld.h>								
#include <Physics/Dynamics/Entity/hkpRigidBody.h>							
#include <Physics/Utilities/Dynamics/Inertia/hkpInertiaTensorComputer.h>	
#include <Physics/Utilities/Constraint/Keyframe/hkpKeyFrameUtility.h>

#include <Physics/Dynamics/Constraint/Bilateral/Prismatic/hkpPrismaticConstraintData.h>
#include <Physics/Dynamics/Constraint/Bilateral/StiffSpring/hkpStiffSpringConstraintData.h>

#include <Common/Base/Thread/Job/ThreadPool/Cpu/hkCpuJobThreadPool.h>
#include <Common/Base/Thread/Job/ThreadPool/Spu/hkSpuJobThreadPool.h>
#include <Common/Base/Thread/JobQueue/hkJobQueue.h>

// Visual Debugger includes
#include <Common/Visualize/hkVisualDebugger.h>
#include <Physics/Utilities/VisualDebugger/hkpPhysicsContext.h>		

#include <Physics/Collide/Shape/Compound/Collection/List/hkpListShape.h>
#include <Physics/Collide/Shape/Misc/Transform/hkpTransformShape.h>

#include "Timer.h"
#include <vector>

using namespace std;

#define NULL 0


// singleton for the Havok gameworld
class HavokWorld
{
public:
	hkpWorld* physicsWorld;

	// make this a singleton
	static HavokWorld& Get()
	{
		if(!theHavokWorld)
		{
			theHavokWorld = new HavokWorld();
		}

		return *theHavokWorld;
	}

	static void Kill()
	{
		if(theHavokWorld)
		{
			theHavokWorld->Cleanup();
			delete theHavokWorld;

		}
	}

	static void HK_CALL errorReport(const char* msg, void* userArgGivenToInit)
	{
		//	printf("%s", msg);
	}

	void Init();
	void Update();
	void StartVisualDebugger();
	hkReal GetTimestep();
	void RemoveFromWorld(hkpRigidBody* body);


	void Lock();
	void Unlock();

private:
	//private constructor
	HavokWorld(void);

	static HavokWorld* theHavokWorld;
	hkJobThreadPool* threadPool;
	hkJobQueue* jobQueue;
	hkVisualDebugger* vdb;
	hkpPhysicsContext* context;
	hkReal timestep;

	vector<hkpRigidBody*> ToBeRemoved;

	void SetupJobQueue();
	void SetupHavokWorld();
	void Cleanup();

};
